#include "algorithm.h"
#include "hal.h"
#include "ckit_config.h"

#define ONE_CYCLE_MM    (PARAMETER_SIXTY_RPM_SPEED*1000/3600)  //mm
#define ONE_KM_MJ_MIN   (PARAMETER_ONE_KM_CAL_MIN * 4186) // mJ
#define ONE_KM_MJ_MAX   (PARAMETER_ONE_KM_CAL_MAX * 4186) // mJ

static _attribute_data_retention_ u16 mTimer;
static _attribute_data_retention_ u32 mDistance;
static _attribute_data_retention_ u32 mCalorie;
static _attribute_data_retention_ u32 mCounter;
static _attribute_data_retention_ u32 mSensorCounter;
static _attribute_data_retention_ u16 cur_speed;
static _attribute_data_retention_ u8 cur_resistance;
static _attribute_data_retention_ u8 cur_incline;
static _attribute_data_retention_ u16 cur_rpm;
static _attribute_data_retention_ u8 cur_heartrate;
static _attribute_data_retention_ u16 cur_power;

static _attribute_data_retention_ u8 cur_error;

static _attribute_data_retention_ u8 mH;
static _attribute_data_retention_ u32 mF;

void algorithm_init(void)
{
	mH = 1;
	mF = 0;
	cur_resistance = RESIS_LEVEL_MIN;
    algorithm_reset_data(1);
}


void algorithm_reset_data(u8 reset_rpm_speed)
{
    mTimer = 0;
    mDistance = 0;
    mCalorie = 0;
    mCounter = 0;
    mSensorCounter = 0;
    cur_incline = 0;
    if(reset_rpm_speed)
    {
        cur_speed = 0;
        cur_rpm = 0;
    }
    cur_heartrate = 0;
    cur_power = 0;
	cur_error = 0;
}

void algorithm_timer_add(void)
{
    mTimer++;
}

void algorithm_set_error(u8 err_num)
{
	static u8 last_error = 0;
	
	if(err_num != 0 && last_error == 0)
	{
		if(err_num == 0x03)
		{
			beep_beep_enable(10);
		}else{
			beep_beep_enable(3);
		}
	}
	last_error = err_num;
	cur_error = err_num;
}

u8 algorithm_get_error(void)
{
	return cur_error;
}

void algorithm_set_cur_resistance(u8 val)
{
    if(val >= RESIS_LEVEL_MIN && val <= RESIS_LEVEL_MAX)
    {
        cur_resistance = val;
    }
}

u8 algorithm_get_cur_resistance(void)
{
	return cur_resistance;
}

void algorithm_set_cur_incline(u8 val)
{
    cur_incline = val;
}

void algorithm_set_cur_rpm(u16 val)
{
    cur_rpm = (val/mH);

    if(val == 0)
    {
        cur_rpm = 0;
        cur_speed = 0;
        cur_power = 0;
    }else{
		cur_speed = (cur_rpm * ONE_CYCLE_MM * 60) / 10000; // 0.01km/h
		cur_power = (mF * cur_speed * 10) / 3600 / 4;		//%25
		if(cur_power > 10000)
		{
			cur_power = 10000;
		}
	}
}

void algorithm_set_cur_heartrate(u8 val)
{
    cur_heartrate = val;
}

void algorithm_counter_add(void)
{
    mCounter++;
	algorithm_sensor_counter_add();
}

void algorithm_sensor_counter_add(void)
{
    static u32 mRealCounter = 0;
    mSensorCounter++;
    mRealCounter = mSensorCounter/mH;
	mF = ((ONE_KM_MJ_MAX - ONE_KM_MJ_MIN)/RESIS_LEVEL_MAX*(cur_resistance - RESIS_LEVEL_MIN) + ONE_KM_MJ_MIN)/100000;
    mCalorie += (mF * ONE_CYCLE_MM) / 4186; // 0.1cal
    mDistance = (u32)(mRealCounter * ONE_CYCLE_MM / 1000);
}

void algorithm_get_sport_data(u16 *time, u16 *distance, u16 *calorie, u16 *counter)
{
    u32 mDistanceTmp = 0;
    *time = mTimer;
    if(hal_config_get_unit_type())
    {
        mDistanceTmp = (mDistance * 62) / 100;
        if(mDistanceTmp > 32000)
        {
            mDistanceTmp = mDistanceTmp/10;
            mDistanceTmp |= 0x8000;
        }
        *distance = (u16)(mDistanceTmp&0xffff);
    }else{
        mDistanceTmp = mDistance;
        if(mDistanceTmp > 32000)
        {
            mDistanceTmp = mDistanceTmp/10;
            mDistanceTmp |= 0x8000;
        }
        *distance = (u16)(mDistanceTmp&0xffff);
    }
    *calorie = mCalorie/1000;
    *counter = (mCounter)&0xffff;
}

void algorithm_get_cur_data(u16 *c_speed, u8 *c_resistance, u8 *c_incline, u16 *c_rpm, u8 *c_heartrate, u16 *c_power)
{
    if(hal_config_get_unit_type())
    {
        *c_speed = (cur_speed * 62) / 100;
    }else{
        *c_speed = cur_speed;
    }
    *c_resistance = cur_resistance;
    *c_incline = cur_incline;
    *c_rpm = cur_rpm;
    *c_heartrate = cur_heartrate;
    *c_power = cur_power;
}
